//
//  Api.m
//  iNews
//
//  Created by baboy on 13-4-18.
//  Copyright (c) 2013年 baboy. All rights reserved.
//

#import "BKApi.h"
#import "DBCache.h"
#import "FileCache.h"
#import "Mem.h"
#import "NSString+x.h"
#import "NSArray+x.h"
#import "BKHttp.h"
#import "AppVersion.h"

#define CACHE_DOMAIN_API @"_API_"
#define CACHE_KEY_DOMAIN @"domain"
#define CACHE_KEY_HANDLER @"handler"

@implementation BKApi
+ (Class)handler{
    NSString *cls = [DBCache valueForKey:@"handler" domain:@"api"];
    if (cls) {
        Class c = NSClassFromString(cls);
        if (c) {
            return c;
        }
    }
    return self;
}
+ (void)initialize{
    [self loadFile:@"app"];
}
+ (BKHttpRequestManager *)sharedHttpRequestManager{
    static BKHttpRequestManager *manager = nil;
    static dispatch_once_t onceHttpRequestManager;
    dispatch_once(&onceHttpRequestManager, ^{
        manager = [BKHttpRequestManager manager];
        manager.requestPool = [BKHttpRequestPool defaultPool];
    });
    return manager;
}
+ (void)loadFile:(NSString *)plist{
    NSString *f = getBundleFilePath([NSString stringWithFormat:@"%@.api.plist", plist], nil);
    if(!f){
        return;
    }
    NSDictionary *conf = [NSDictionary dictionaryWithContentsOfFile:f];
    NSString *server = [conf valueForKey:CACHE_KEY_DOMAIN];
    NSArray *ignores = @[CACHE_KEY_DOMAIN, CACHE_KEY_HANDLER];
    NSMutableDictionary *data = [NSMutableDictionary dictionary];
    for (NSString *k in [conf allKeys]) {
        id api = [conf valueForKey:k];
        if (!api) {
            continue;
        }
        if ([api isKindOfClass:[NSDictionary class]]) {
            api = [NSMutableDictionary dictionaryWithDictionary:api];
            NSString *url = [api valueForKey:@"url"];
            if (![ignores containsStringIgnoreCase:k] && ![url isURL] && server) {
                url = [NSString stringWithFormat:@"%@%@", server, url];
                [api setValue:url forKey:@"url"];
            }
        }
        
        [data setValue:api forKey:k];
        //[DBCache setValue:v forKey:k domain:CACHE_DOMAIN_API];
    }
    [Mem setValue:data forKey:CACHE_DOMAIN_API];
}

+ (BOOL)setCommonParams:(NSDictionary *)params{
    [Mem setValue:params forKey:@"api_common_params"];
    return true;
}
+ (NSDictionary *)commonParams{
    NSDictionary *d = [Mem valueForKey:@"api_common_params"];
    return d;
}

+ (NSDictionary *)apiForKey:(NSString *)key{
//    NSDictionary *api = [DBCache valueForKey:key domain:CACHE_DOMAIN_API];
    NSDictionary *data = [Mem valueForKey:CACHE_DOMAIN_API];
    NSDictionary *api = [data valueForKey:key];
    return api;
}
+ (NSString *)urlForKey:(NSString *)key{
    NSDictionary *api = [self apiForKey:key];
    NSString *v = [api valueForKey:@"url"];
    NSString *url = [v URLStringWithParam:[self commonParams]];
    return url;
}
+ (NSString *)urlForKey:(NSString*)key withParam:(NSDictionary *)param{
    NSString *v = [self urlForKey:key];
    if (param) {
        v = [v URLStringWithParam:param];
    }
    return v;
}
+ (nullable id) request:(NSString * _Nullable)apiKey
             parameters:(nullable id)parameters
                success:(nullable void (^)(id _Nonnull task, id _Nullable json))success
                failure:(nullable void (^)(id _Nullable task,id _Nullable json, NSError * _Nonnull error))failure{
    NSDictionary *api = [self apiForKey:apiKey];
    if(!api){
        return nil;
    }
    NSString *url = [api valueForKey:@"url"];
    id needCommonParams = [api valueForKey:@"need_common_params"];
    if (!needCommonParams || [needCommonParams boolValue]) {
        NSDictionary *commonParams = [self commonParams];
        url = [url URLStringWithParam:commonParams];
    }
    url = [url replaceholders:parameters];
    NSString *method = [api valueForKey:@"method"];
    id param = parameters;
    if ([parameters respondsToSelector:@selector(dict)]) {
        param = [parameters dict];
    }
    NSDictionary *headers = [api valueForKey:@"headers"];
    BKHttpRequestManager *manager = [self sharedHttpRequestManager];
    
    if ([@"POST" isEqualToString:method]) {
        NSString *contentType = headers?[headers valueForKey:@"content-type"]:nil;
        if (contentType && [contentType indexOf:@"json"]>=0) {
            manager.requestSerializer = [AFJSONRequestSerializer serializer];
            manager.requestSerializer.timeoutInterval = 90.0f;
        }
        id task = [manager POST:url
                     parameters:param
                       progress:^(NSProgress *uploadProgress){
            
                        }
                        success:^(id  _Nonnull task, id  _Nullable responseObject) {
                            success(task, responseObject);
                        }
                        failure:^(id  _Nonnull task, NSError * _Nonnull error) {
                            failure(task, nil, error);
                        }];
        return task;
    }
    id task = [manager getJSON:url
                                                  parameters: param
                                                 cachePolicy:BKHttpRequestCachePolicyFallbackToCacheIfLoadFails
                                                     success:^(id  _Nonnull task, id  _Nullable json) {
                                                         success(task, json);
                                                     }
                                                     failure:^(id  _Nullable task, id  _Nullable json, NSError * _Nonnull error) {
                                                         failure(task, json, error);
                                                     }];
    return task;
}

+ (nullable id) request:(NSString * _Nullable)apiKey
             parameters:(nullable id)parameters
               callback:(nullable void (^)(id _Nonnull task, id _Nullable json, NSError * _Nullable error))callback{
    id task = [self request:apiKey
                 parameters:parameters
                    success:^(id  _Nonnull task, id  _Nullable json) {
                        if (callback) {
                            callback(task,json, nil);
                        }
                    }
                    failure:^(id  _Nullable task, id  _Nullable json, NSError * _Nonnull error) {
                        if (callback) {
                            callback(task,json,error);
                        }
                    }];
    return task;
}

+ (void)checkVersionSuccess:(nullable void (^)(id _Nonnull task, id _Nullable json))success
                    failure:(nullable void (^)(id _Nullable, id _Nullable, NSError * _Nonnull))failure{
    [self request:@"check_version"
       parameters:nil
          success:^(id  _Nonnull task, id  _Nullable json) {
              HttpResponse *res = [HttpResponse responseWithDictionary:json dataItemClass:[AppVersion class]];
              if ([res isSuccess]) {
                  success(task, res);
                  return;
              };
              NSError *error = [NSError errorWithDomain:@"" code:0 userInfo:@{NSLocalizedDescriptionKey:[res msg]}];
              failure(task, json, error);
          }
          failure:^(id  _Nullable task, id  _Nullable json, NSError * _Nonnull error) {
              failure(task, json, error);
          }];
}
@end

